/*
 * Socket.h
 *
 *  Created on: 2009-3-19
 *      Author: W. Wen Peng
 */

#ifndef SOCKET_H_
#define SOCKET_H_

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>

#include "Object.h"
#include "Types.h"
#include "epoll/EpollHandler.h"

class Socket: public EpollHandler {
protected:
	SOCKET 			m_socket;
	sa_family_t		m_sin_family;
	SockAddr*		m_peer_addr;
	SockAddr*		m_local_addr;
	bool			m_passive;	//Is this a passive socket,	e.g.listenner.
	EventType		m_event;		//添加关注的Event
//	int SetMode(int mode);			//设置socket工作模式:O_NONBLOCK非阻塞，
protected:
	virtual int ReadBlock(byte * buf, size_t blokmaxlen); 	//成功返回实际快大小，失败则返回负数（错误号相反数）
	virtual int WriteBlock(const byte * buf, size_t bloklen); 	//成功返回实际写入大小

public:
	virtual int Connect();
	virtual int Bind();
	virtual int Listen();
	virtual int Accept(Socket & socket);
	int SetNonBlock();

	Socket():m_event(0),m_socket(-1),m_passive(false),m_sin_family(AF_INET){
		m_peer_addr =new SockAddr();
		m_local_addr =new SockAddr();
		bzero(m_peer_addr,sizeof(*m_peer_addr));
		bzero(m_local_addr,sizeof(*m_local_addr));
	}
	//create a socket by specified socket descripter
	void Create(SOCKET socket);
	SOCKET	Create(int family,	int type, int protocol, bool is_passive = false);

	void SetReuseAddr(){
		int opt =1;
		int len =sizeof(opt);
		setsockopt(m_socket,SOL_SOCKET,SO_REUSEADDR,&opt,len);
	}

	SOCKET GetSocketFd(){
		return m_socket;
	}
	SockAddr & GetPeerAddr() {
//		socklen_t len =0;
//		getpeername(m_socket,(sockaddr*)m_peer_addr,&len);
		return *m_peer_addr;
	}
	SockAddr & GetLocalAddr() {
//		socklen_t len =0;
//		getsockname(m_socket,(sockaddr*)m_peer_addr,&len);
		return *m_local_addr;
	}

	void SetLocalIp(const char *src_ip){
//		m_local_addr->sin_addr.s_addr =htonl(Utility::StrToIp(src_ip));
		inet_pton(m_sin_family,src_ip,&m_local_addr->sin_addr);
	}
	void SetLocalPort(uint16_t port){
		m_local_addr->sin_port = htons( port );
	}
	void SetPeerIp(const char * dst_ip){
//		m_peer_addr->sin_addr.s_addr =htonl(Utility::StrToIp(dst_ip));
		//inet_pton(m_sin_family,dst_ip,&m_peer_addr->sin_addr);
		m_peer_addr->sin_addr.s_addr = inet_addr(dst_ip);
	}
	void SetPeerPort(uint16_t dport){
		m_peer_addr->sin_port = htons( dport );
	}
//
	//===========EpollHandler 接口================
	fd_t GetFd() const {
		return m_socket;
	}
	int OnError(Epoller &sender, EpollEventArg &e){
		return -errno;
	}
	EventType GetEvents() const{
		return m_event;
	}
	int OnTimeOut(Epoller &sender, EpollEventArg &e){
		return 0;
	}
	//=================end EpollerHandler====================

	virtual ~Socket();
	virtual int Close(){
		int flg = close(m_socket);
		debug("close a socket:%d,flg:%d\n",m_socket, flg);
		m_socket = -1;		//invai
		return flg;
	}
	void Finalize();			//Object::Finalize();垃圾回收
};

#endif /* SOCKET_H_ */
